package com.tools.common.object.json;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.tools.common.container.JsonPair;
import com.tools.common.container.OwnPairs;
import com.tools.common.container.OwnRows;
import com.tools.common.object.DateKit;
import com.tools.common.object.Note;
import com.tools.common.object.ObjKit;
import com.tools.web.interceptor.auth.GenericAuthUser;
import com.tools.web.interceptor.auth.MultiAuthUser;
import com.tools.web.interceptor.auth.SingleAuthUser;

import java.io.IOException;
import java.lang.reflect.Field;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Jackson 的自定义序列化器处理器工具类
 * */
@Note("Jackson 的自定义序列化器处理器工具类")
public class SerializerHandler {

    protected SerializerHandler() {}

    /* *******************************************************************************************
     *
     *          返回所有的反序列化器
     *
     * *******************************************************************************************
     * */

    @Note("获取所有的 JsonSerializer 序列化器")
    public static Map<Class, JsonSerializer> all() {
        Map<Class, JsonSerializer> map = new HashMap<>((int) (8/0.75) + 1);
        //日期时间
        map.put(LocalDateTime.class, localDateTimeSerializer());
        map.put(LocalDate.class, localDateSerializer());
        map.put(LocalTime.class, localTimeSerializer());
        map.put(Date.class, dateSerializer());
        //自定义容器
        map.put(OwnPairs.class, ownPairsSerializer());
        map.put(OwnRows.class, ownRowsSerializer());
        //AuthUser
        map.put(SingleAuthUser.class, singleAuthUserSerializer());
        map.put(MultiAuthUser.class, multiAuthUserSerializer());
        return map;
    }

    /* *******************************************************************************************
     *
     *          日期的反序列化
     *
     * *******************************************************************************************
     * */

    @Note("Java 1.8 时的日期时间类 LocalDateTime 的序列化逻辑")
    public static JsonSerializer<LocalDateTime> localDateTimeSerializer() {
        return new JsonSerializer<LocalDateTime>() {
            @Override
            public void serialize(LocalDateTime dateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
                if (JsonKit.DEFAULT_DATETIME_FORMATTER == null) {
                    long timestamp = DateKit.timestamp(dateTime);
                    jsonGenerator.writeNumber(timestamp);
                } else {
                    jsonGenerator.writeString(JsonKit.DEFAULT_DATETIME_FORMATTER.format(dateTime));
                }
            }
        };
    }


    @Note("自定义 Java 1.8 的日期时间类 LocalDate 的序列化逻辑")
    public static JsonSerializer<LocalDate> localDateSerializer() {
        return new JsonSerializer<LocalDate>() {
            public void serialize(LocalDate date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
                if (JsonKit.DEFAULT_DATE_FORMATTER == null) {
                    long timestamp = DateKit.timestamp(date);
                    jsonGenerator.writeNumber(timestamp);
                } else {
                    jsonGenerator.writeString(JsonKit.DEFAULT_DATE_FORMATTER.format(date));
                }
            }
        };
    }


    @Note("自定义 Java 1.8 的时间类 LocalTime 的序列化逻辑")
    public static JsonSerializer<LocalTime> localTimeSerializer() {
        return new JsonSerializer<LocalTime>() {
            public void serialize(LocalTime time, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
                if (JsonKit.DEFAULT_TIME_FORMATTER == null) {
                    long timestamp = DateKit.timestamp(time);
                    jsonGenerator.writeNumber(timestamp);
                } else {
                    jsonGenerator.writeString(JsonKit.DEFAULT_TIME_FORMATTER.format(time));
                }
            }
        };
    }


    @Note("日期时间类 Date 的序列化逻辑")
    public static JsonSerializer<Date> dateSerializer() {
        return new JsonSerializer<Date>() {
            public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
                if (JsonKit.DEFAULT_DATETIME_FORMATTER == null) {
                    jsonGenerator.writeNumber(date.getTime());
                } else {
                    jsonGenerator.writeString(DateKit.format(date, JsonKit.DEFAULT_DATETIME_FORMATTER));
                }
            }
        };
    }

    /* *******************************************************************************************
     *
     *          容器类的反序列化
     *
     * *******************************************************************************************
     * */

    @Note("自定义键值对集合容器类 OwnPairs 的序列化逻辑")
    public static JsonSerializer<OwnPairs> ownPairsSerializer() {
        return new JsonSerializer<OwnPairs>() {
            public void serialize(OwnPairs pairs, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
                if(pairs.initialized()) {
                    jsonGenerator.writeStartObject();
                    for(Object o : pairs.entrySet()) {
                        Map.Entry e = (Map.Entry) o;
                        jsonGenerator.writeObjectField(ObjKit.toStringNullString(e.getKey()), e.getValue());
                    }
                    jsonGenerator.writeEndObject();
                    return;
                }
                if(pairs instanceof JsonPair) {
                    JsonPair jsonPair = (JsonPair) pairs;
                    jsonGenerator.writeStartObject();
                    jsonGenerator.writeNumberField(JsonPair.CODE, jsonPair.getCode());
                    jsonGenerator.writeStringField(JsonPair.MESSAGE, jsonPair.getMessage());
                    Object data = jsonPair.getData();
                    if(data != null) {
                        jsonGenerator.writeObjectField(JsonPair.DATA, data);
                    }
                    jsonGenerator.writeEndObject();
                }
            }
        };
    }


    @Note("自定义数组集合容器类 OwnRows 的序列化逻辑")
    public static JsonSerializer<OwnRows> ownRowsSerializer() {
        return new JsonSerializer<OwnRows>() {
            @Override
            public void serialize(OwnRows row, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
                jsonGenerator.writeStartArray();
                for(Object obj : row) {
                    jsonGenerator.writeObject(obj);
                }
                jsonGenerator.writeEndArray();
            }
        };
    }


    /* *******************************************************************************************
     *
     *          AuthUser 的反序列化
     *
     * *******************************************************************************************
     * */

    @Note("SingleAuthUser 类的自定义序列化逻辑")
    public static JsonSerializer<SingleAuthUser> singleAuthUserSerializer() {
        return new JsonSerializer<SingleAuthUser>() {
            @Override
            public void serialize(SingleAuthUser singleAuthUser, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
                jsonGenerator.writeStartObject();
                jsonGenerator.writeStringField("uuid", singleAuthUser.getUuid());
                jsonGenerator.writeStringField("deviceTypeId", singleAuthUser.getDeviceTypeId());
                jsonGenerator.writeStringField("userType", singleAuthUser.getUserType());
                protected_authUserWrite(singleAuthUser, jsonGenerator);
                jsonGenerator.writeEndObject();
            }
        };
    }


    @Note("MultiAuthUser 类的自定义序列化逻辑")
    public static JsonSerializer<MultiAuthUser> multiAuthUserSerializer() {
        return new JsonSerializer<MultiAuthUser>() {
            @Override
            public void serialize(MultiAuthUser multiAuthUser, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
                jsonGenerator.writeStartObject();
                Field field = ObjKit.getField(MultiAuthUser.class, "deviceAndLoginRecord");
                Object deviceAndLoginRecord = ObjKit.getFieldValue(multiAuthUser, field);
                jsonGenerator.writeObjectField("deviceAndLoginRecord", deviceAndLoginRecord);
                protected_authUserWrite(multiAuthUser, jsonGenerator);
                jsonGenerator.writeEndObject();
            }
        };
    }


    /* *******************************************************************************************
     *
     *          私有逻辑
     *
     * *******************************************************************************************
     * */


    @Note("写入 GenericAuthUser 部分的公共属性")
    protected static void protected_authUserWrite(GenericAuthUser authUser, JsonGenerator jsonGenerator) throws IOException {
        jsonGenerator.writeObjectField("userId", authUser.getUserId());
        jsonGenerator.writeObjectField("user", authUser.getUser());
        jsonGenerator.writeStringField("userTypeClass", authUser.getUserTypeClass().getName());
        jsonGenerator.writeObjectField("roleKeyMap", authUser.getRoleKeyMap());
        jsonGenerator.writeObjectField("permissionKeyMap", authUser.getPermissionKeyMap());
        jsonGenerator.writeObjectField("routerList", authUser.getRouterList());
        Field customDataField = ObjKit.getField(GenericAuthUser.class, "customData");
        Object customData = ObjKit.getFieldValue(authUser, customDataField);
        jsonGenerator.writeObjectField("customData", customData);
    }



}
